package com.web.security.filter;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.common.apiresult.ResultCode;
import com.common.constant.RedisConstant;
import com.common.exception.BusinessException;
import com.common.utils.JwtTokenUtil;
import com.common.utils.RedisUtil;
import com.system.entity.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author liuxuhuang
 * @date 2023年04月02日 9:48
 */
@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RequestMatcher[] NoRequestMatchers;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        /**
         * 如果请求路径在放行名单中，则放行
         */
        if (requestURLPass(request)) {
            log.info("放行== " + request.getRequestURI());
            filterChain.doFilter(request, response);
            return;
        }
        String token = jwtTokenUtil.getToken(request);
        if (StringUtils.isBlank(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        log.info("token=" + token);
        long userId = jwtTokenUtil.getUserId(token);
        String redisKey = RedisConstant.LOGIN_USER_PREFIX + userId;
        if (!redisUtil.hasKey(redisKey)) {
            throw new BusinessException(ResultCode.UNAUTHORIZED);
        }
        LoginUser loginUser = (LoginUser) redisUtil.get(redisKey);
        log.info("登录用户：" + loginUser.getUsername());
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        filterChain.doFilter(request, response);
    }

    /**
     * 匹配请求路径是否在放行列表中
     * true 放行
     * false 拦截
     *
     * @param request
     * @return
     */
    public boolean requestURLPass(HttpServletRequest request) {
        if (NoRequestMatchers == null || NoRequestMatchers.length <= 0) {
            return false;
        }
        for (RequestMatcher requestMatcher : NoRequestMatchers) {
            if (requestMatcher.matches(request)) {
                return true;
            }
        }
        return false;
    }
}
